﻿//======================================================================
//
//        Copyright : Zhengzhou Strawberry Computer Technology Co.,LTD.
//        All rights reserved
//        
//        Application:NFinal MVC framework
//        Filename :Router.cs
//        Description :路由类
//
//        created by Lucas at  2015-6-30`
//     
//        WebSite:http://www.nfinal.com
//
//======================================================================
using System;
using System.Collections.Generic;
using System.Web;
using System.Threading;
using System.Globalization;
using System.Collections.Specialized;

namespace ${namespace}
{
    public class Router
    {
		private string GetString(string val, string de)
        {
            return string.IsNullOrEmpty(val) ? de : val;
        }
        private string UCFirst(string val)
        {
            CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;
            return cultureInfo.TextInfo.ToTitleCase(val);
        }
        private static void Callback(IAsyncResult result)
        {
            //结束异步写入
            System.IO.FileStream stream = (System.IO.FileStream)result.AsyncState;
            stream.EndWrite(result);
            stream.Close();
        }
		//设置浏览器缓存
        public void SetBrowerCache(HttpContext context,int optimizing,int seconds)
        {
            //浏览器缓存
            if ((optimizing & 224) != 0)
            {
                context.Response.Cache.SetCacheability(HttpCacheability.Public);
                //NotModify
                if ((optimizing & 32) != 0)
                {
                    context.Response.Cache.SetLastModifiedFromFileDependencies();
                }
                //Expires
                else if ((optimizing & 64) != 0)
                {
                    context.Response.Cache.SetExpires(DateTime.Now.AddSeconds(seconds));
                }
                //NoExpires
                else if ((optimizing & 128) != 0)
                {
                }
            }
            else
            {
                //不进行缓存
                context.Response.Cache.SetNoStore();
            }
        }
        //设置服务器缓存
        public void SetServerCacheAndOutPut(HttpContext context, string app, string urlWithOutAppAndExt, string url, byte[] buffer, int optimizing, int seconds)
        {
            //服务器缓存
            if ((optimizing & 14) != 0)
            {
                //FileDependency
                if ((optimizing & 2) != 0)
                {
                    string fileName = context.Server.MapPath(app + "/HTML" + urlWithOutAppAndExt + ".html");
                    //将HTML写入静态文件
                    if (!System.IO.File.Exists(fileName))
                    {
                        string dir = System.IO.Path.GetDirectoryName(fileName);
                        if (!System.IO.Directory.Exists(dir))
                        {
                            System.IO.Directory.CreateDirectory(dir);
                        }
                        System.IO.FileStream file = new System.IO.FileStream(fileName, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite, 1024, true);
                        file.BeginWrite(buffer, 0, buffer.Length, new AsyncCallback(Callback), file);
                    }
                    //将HTML插入新的缓存
                    System.Web.Caching.CacheDependency dep = new System.Web.Caching.CacheDependency(fileName);
                    HttpRuntime.Cache.Insert(url, buffer, dep, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration);
                }
                //AbsoluteExpiration
                else if ((optimizing & 4) != 0)
                {
                    HttpRuntime.Cache.Insert(url, buffer, null, DateTime.Now.AddSeconds(seconds), System.Web.Caching.Cache.NoSlidingExpiration);
                }
                //SlidingExpiration
                else if ((optimizing & 8) != 0)
                {
                    HttpRuntime.Cache.Insert(url, buffer, null, System.Web.Caching.Cache.NoAbsoluteExpiration, new TimeSpan(0, 0, seconds));
                }
            }
            //直接输出
            context.Response.OutputStream.Write(buffer, 0, buffer.Length);
            context.Response.OutputStream.Close();
        }
        //写入缓存
        public bool WriteCache(HttpContext context,string url,int optimizing)
        {
            object cache = null;
            //服务器缓存
            if ((optimizing & 14) != 0)
            {
                cache = HttpRuntime.Cache.Get(url);
                //如果缓存存在则直接输出.
                if (cache != null)
                {
                    System.IO.Stream stream = null;
                    if ((optimizing & 1536) != 0)
                    {
                        if ((optimizing & 512) != 0)
                        {
                            context.Response.AppendHeader("Content-encoding", "gzip");
                        }
                        else if ((optimizing & 1024) != 0)
                        {
                            context.Response.AppendHeader("Content-encoding", "deflate");
                        }
                    }
                    byte[] buffer= (byte[])cache;
                    context.Response.OutputStream.Write(buffer, 0, buffer.Length);
                    context.Response.OutputStream.Close();
                    return true;
                }
            }
            return false;
        }
        public void Run(System.Web.HttpContext context,string subdomain,string app,string urlWithOutAppAndExt,string controller,string action,NameValueCollection get)
        {
			switch (controller)
			{
				${foreach(classData in classDataList)}
				//relativeName="/Manage/IndexController"
				//RelativeDotName=".Manage.IndexController"
				case "${classData.relativeName}":
					{
                        
						switch (action)
						{
							${set(classDataMethodDataList=classData.MethodDataList)}
							${foreach(method in classDataMethodDataList)}
							${if(method.isPublic)}
							case "${method.name}": 
							{
								${method.verifyCode}
								${if(method.optimizing==0)}
								Web.${defaultStyle}${classData.relativeDotName}.${method.name}Action control= new Web.${defaultStyle}${classData.relativeDotName}.${method.name}Action(context.Response.Output);
								${set(methodparameterDataList=method.parameterDataList)}
								$foreach(parameterData in methodparameterDataList)
									${parameterData.getParamterCode}
								$end
								control._cookies = new Common.Data.CookieManager(context);
								control._context = context;
								control._subdomain = subdomain;
								control._url=context.Request.RawUrl;
								control._get = get;
								control._app=app;
								control._controller = controller;
                                control._action = action;
								control.Before();
								control.${method.name}(${method.parameterNames});
								control.After();
								break;
								${else}
								 //优化选项
                                int optimizing = ${method.optimizing};
                                int seconds = ${method.seconds};
                                string url = string.Format("{0}{1}.htm", app, urlWithOutAppAndExt);
                                bool compress = (optimizing & 1536)!=0;
                                //设置浏览器缓存
                                SetBrowerCache(context, optimizing, seconds);
                                //是否启用了服务器缓存
                                bool serverCahce = (optimizing & 14) != 0;
                                bool hasCache = false;
                                //服务器缓存
                                if (serverCahce)
                                {
                                    hasCache=WriteCache(context,url,optimizing);
                                }
                                //如果没有缓存
                                if (!hasCache)
                                {
                                    System.IO.MemoryStream htmlStream = new System.IO.MemoryStream();
                                    
                                    Web.${defaultStyle}${classData.relativeDotName}.${method.name}Action control = null;
                                    System.IO.Stream stream = null;
                                    System.IO.StreamWriter sw = null;
                                    //如果有压缩或缓存
                                    if (compress || serverCahce)
                                    {
                                        if ((optimizing & 1536) != 0)
                                        {
                                            if ((optimizing & 512) != 0)
                                            {
                                                stream = new System.IO.Compression.GZipStream(htmlStream, System.IO.Compression.CompressionMode.Compress, true);
                                                context.Response.AppendHeader("Content-Encoding", "gzip");
                                            }
                                            else if ((optimizing & 1024) != 0)
                                            {
                                                stream = new System.IO.Compression.DeflateStream(htmlStream, System.IO.Compression.CompressionMode.Compress, true);
                                                context.Response.AppendHeader("Content-Encoding", "deflate");
                                            }
                                            sw = new System.IO.StreamWriter(stream);
                                        }
                                        else
                                        {
                                            sw = new System.IO.StreamWriter(htmlStream);
                                        }
                                        control = new Web.${defaultStyle}${classData.relativeDotName}.${method.name}Action(sw);
                                    }
                                    else
                                    {
                                        control = new Web.${defaultStyle}${classData.relativeDotName}.${method.name}Action(context.Response.Output);
                                    }
									${set(methodparameterDataList=method.parameterDataList)}
									$foreach(parameterData in methodparameterDataList)
										${parameterData.getParamterCode}
									$end
                                    control._cookies = new Common.Data.CookieManager(context);
                                    control._context = context;
                                    control._subdomain = subdomain;
                                    control._url = context.Request.RawUrl;
                                    control._get = get;
                                    control._app = app;
                                    control._controller = controller;
                                    control._action = action;
                                    control.Before();
                                    control.${method.name}(${method.parameterNames});
                                    control.After();
                                    control.Close();
                                    byte[] buffer = htmlStream.ToArray();
									htmlStream.Close();
                                    //如果有压缩或缓存
                                    if (compress || serverCahce)
                                    {
                                        SetServerCacheAndOutPut(context, app, urlWithOutAppAndExt, url, buffer, optimizing, seconds);
                                    }
								}
								break;
								${end}
							}
							${end}
							${end}
							default: context.Response.Write("找不到类" + controller + "下的" + action + "方法");context.Response.End(); break;
						}
						break;
					}
				${end}
				default: context.Response.Write("找不到类" + controller); context.Response.End(); break; 
			}
        }
        
    }
}